package br.com.rotary.servico;

import br.com.rotary.enums.Relatorio;
import br.com.rotary.enums.TipoConvidado;
import br.com.rotary.enums.TipoParticipante;
import br.com.rotary.generico.ServicoGenerico;
import br.com.rotary.modelo.Clube;
import br.com.rotary.modelo.Estado;
import br.com.rotary.modelo.FichaInscricao;
import br.com.rotary.utilitario.Msg;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import javax.ejb.Stateless;
import javax.faces.context.FacesContext;
import javax.persistence.Query;
import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperRunManager;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.fill.JRAbstractLRUVirtualizer;
import net.sf.jasperreports.engine.fill.JRSwapFileVirtualizer;
import net.sf.jasperreports.engine.util.JRSwapFile;

/**
 *
 * @author laverson
 */
@Stateless
public class RelatorioServico extends ServicoGenerico<FichaInscricao> {

    public RelatorioServico() {
        super(FichaInscricao.class);
    }

    public Long quantidadeGeral(boolean rotarianos) {
        String sql = "select count(f) from " + FichaInscricao.class.getSimpleName() + " f "
                + "where f.ativo = true ";

        if (rotarianos) {
            sql += "AND f.tipoParticipante like '" + TipoParticipante.ROTARIANO.name() + "'";
        } else {
            sql += "AND (f.tipoParticipante like '" + TipoParticipante.CONVIDADDO.name() + "' ";
            sql += "OR f.tipoParticipante like '" + TipoParticipante.PALESTRANTE.name() + "' ";
            sql += "OR f.tipoConvidado like '" + TipoConvidado.CONJUGE.name() + "' ";
            sql += "OR f.tipoConvidado like '" + TipoConvidado.CONVIDADDO.name() + "' ";
            sql += "OR f.tipoConvidado like '" + TipoConvidado.PALESTRANTE.name() + "') ";
        }

        Query results = getEntityManager().createQuery(sql);

        return (Long) results.getSingleResult();
    }

    public Long quantidadeEstado(Estado estado, TipoParticipante tipoParticipante) {

        if (estado != null && estado.getId() != null) {

            String sql = "SELECT count(f.id) FROM " + FichaInscricao.class.getSimpleName() + " f JOIN f.clube c JOIN c.estado e "
                    + "WHERE e.id = " + estado.getId()
                    + " AND f.ativo = true ";

            if (tipoParticipante != null) {
                sql += "AND f.tipoParticipante like '" + tipoParticipante.name() + "'";
            } else {
                sql += "AND (f.tipoParticipante like '" + TipoParticipante.ROTARIANO.name() + "' ";
                sql += "OR f.tipoParticipante like '" + TipoParticipante.CONVIDADDO.name() + "' ";
                sql += "OR f.tipoParticipante like '" + TipoParticipante.PALESTRANTE.name() + "' ";
                sql += "OR f.tipoConvidado like '" + TipoConvidado.CONJUGE.name() + "' ";
                sql += "OR f.tipoConvidado like '" + TipoConvidado.CONVIDADDO.name() + "' ";
                sql += "OR f.tipoConvidado like '" + TipoConvidado.PALESTRANTE.name() + "') ";
            }

            Query query = getEntityManager().createQuery(sql);

            return (Long) query.getSingleResult();
        }

        return null;
    }

    public Long quantidadeClube(Clube clube, TipoParticipante tipoParticipante) {

        if (clube != null && clube.getId() != null) {

            String sql = "SELECT f FROM " + FichaInscricao.class.getSimpleName() + " f JOIN f.clube c "
                    + "WHERE c.id = " + clube.getId()
                    + " AND f.ativo = true ";

            if (tipoParticipante != null && tipoParticipante.equals(TipoParticipante.ROTARIANO)) {
                sql += " AND f.tipoParticipante not like '" + TipoParticipante.CONVIDADDO.name() + "'";
            }

            Query query = getEntityManager().createQuery(sql);

            List<FichaInscricao> result = query.getResultList();

            Long quantidade = result.size() + 0L;

            if (tipoParticipante != null && TipoParticipante.CONVIDADDO.equals(tipoParticipante)) {
                quantidade = 0L;
            }

            for (FichaInscricao ficha : result) {
                if (tipoParticipante == null || (tipoParticipante != null && !TipoParticipante.ROTARIANO.equals(tipoParticipante))) {
                    if (ficha.getTipoConvidado() != null || ficha.getTipoParticipante().equals(TipoParticipante.CONVIDADDO)) {
                        quantidade++;
                    }
                }
            }

            return quantidade;
        }

        return null;
    }

    @Override
    public void remover(FichaInscricao entity) {
        entity.setAtivo(false);
        atualizar(entity);
    }

    public static void genReport(HashMap<String, Object> parametros, Collection<?> collection, Relatorio relatorio) {
        try {
            if (parametros == null) {
                parametros = new HashMap<String, Object>();
            }
            JRSwapFile file = new JRSwapFile("/tmp", 4096, 10);

            JRAbstractLRUVirtualizer virtualizer = new JRSwapFileVirtualizer(10, file, true);

            parametros.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);

            FacesContext facesContext = FacesContext.getCurrentInstance();
            ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();

            InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream(relatorio.getUrl());

            HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();

            ServletOutputStream ouputStream = response.getOutputStream();

            JRDataSource jrds;
            if (collection != null) {
                jrds = new JRBeanCollectionDataSource(collection);
            } else {
                jrds = new JREmptyDataSource();
            }

            JasperRunManager.runReportToPdfStream(stream, ouputStream, parametros, jrds);

            response.setHeader("Content-Disposition", "inline; filename=\"relatorio.pdf\"");
            response.setContentType("application/pdf");
            facesContext.responseComplete();
            ouputStream.flush();
            ouputStream.close();

        } catch (IOException e) {

            System.err.println(e);
            Msg.messagemError("Erro ao gerar relatório IOEX");

        } catch (JRException e) {

            System.err.println(e);
            Msg.messagemError("Erro ao gerar relatório JREX");
        }
    }

    public static void genReport(byte[] pdfAsBytes) {
        try {
            JRSwapFile file = new JRSwapFile("/tmp", 4096, 10);

            JRAbstractLRUVirtualizer virtualizer = new JRSwapFileVirtualizer(10, file, true);

            FacesContext facesContext = FacesContext.getCurrentInstance();
            ServletContext servletContext = (ServletContext) facesContext.getExternalContext().getContext();

            HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();

            ServletOutputStream ouputStream = response.getOutputStream();

            response.setHeader("Content-Disposition", "inline; filename=\"relatorio.pdf\"");
            response.setContentType("application/pdf");
            facesContext.responseComplete();
            ouputStream.write(pdfAsBytes);

            ouputStream.flush();
            ouputStream.close();

        } catch (IOException e) {

            System.err.println(e);
            Msg.messagemError("Erro ao gerar relatório IOEX");
        }
    }

    public Long valorArrecadadoRotariano(Clube clube) {

        return quantidadeClube(clube, TipoParticipante.ROTARIANO) * 150;
    }

    public Long valorArrecadadoConvidado(Clube clube) {

        return quantidadeClube(clube, TipoParticipante.CONVIDADDO) * 100;
    }
}
